package com.digital.cnzz.zkp.web.controller;

import com.digital.cnzz.zkp.common.exception.BizException;
import com.digital.cnzz.zkp.common.utils.LogUtils;
import com.digital.cnzz.zkp.service.ICalculationExpressConfigService;
import com.digital.cnzz.zkp.ao.*;
import com.digital.cnzz.zkp.common.annotation.AopLog;
import com.digital.cnzz.zkp.common.annotation.RolesAllowed;
import com.digital.cnzz.zkp.common.constants.ResponseEnum;
import com.digital.cnzz.zkp.common.vo.VO;
import com.digital.cnzz.zkp.constant.RuleParamsEnum;
import com.digital.cnzz.zkp.entity.CalculationExpressConfig;
import com.digital.cnzz.zkp.page.CommonPage;
import com.digital.cnzz.zkp.vo.CalculationExpressConfigVO;
import com.ql.util.express.DefaultContext;
import com.ql.util.express.ExpressRunner;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.List;
import java.util.Map;

import static com.digital.cnzz.zkp.common.constants.ModuleConstants.*;
import static com.digital.cnzz.zkp.common.constants.OperateConstants.*;

/**
 * @author liujiang
 * @date 2021/3/30 17:28
 */
@RestController
@Api(tags = "计算规则配置")
@RequestMapping("/expressConfig")
public class CalculationExpressConfigController {
    @Autowired
    ICalculationExpressConfigService iCalculationExpressConfigService;

    @RolesAllowed({"考评办", "组织单位", "考评对象"})
    @ApiOperation(value = "计算规则保存或更新", notes = "计算规则保存或更新")
    @AopLog(logModule = JSGZ_SAVE_UPDATE_MODULE, logType = OPERATE_UPDATE, logDesc = "新增或修改月度计算规则:#{#ao.ruleName}")
    @PostMapping("/saveCalculationExpress")
    @ResponseBody
    public Object saveCalculationExpress(@Valid @RequestBody CalculationExpressConfigSaveAO ao) {
        return iCalculationExpressConfigService.saveCalculationExpressConfig(ao);
    }

    @RolesAllowed({"考评办", "组织单位", "考评对象"})
    @ApiOperation(value = "删除计算规则", notes = "删除计算规则")
    @PostMapping("/deleteRuleById")
    @AopLog(logModule = JSGZ_SAVE_DEL, logType = OPERATE_DELETE, logDesc = "删除计算规则:#{#ao.id}")
    @ResponseBody
    public Object deleteById(@RequestBody CalculationExpressDelAO ao) {
        iCalculationExpressConfigService.deleteById(ao);
        return VO.success();
    }

    @RolesAllowed({"考评办", "组织单位", "考评对象"})
    @ApiOperation(value = "上架或下架", notes = "上架或下架")
    @PostMapping("/updateIsActive")
    @ResponseBody
    public Object updateIsActive(@RequestBody CalculationExpressDelAO ao) {
        boolean b = iCalculationExpressConfigService.updateIsActive(ao.getId());
        if (b) {
            return VO.success();
        }
        return VO.response(ResponseEnum.FAIL);

    }

    /**
     * 分页查询计算规则列表
     *
     * @param params 查询参数
     * @return Object
     */
    @GetMapping("/getRulesPageList")
    @ApiOperation(value = "分页查询计算规则列表")
    public Object getTaskPageList(CalculationExpressConfigPageListAO params) {
        CommonPage<CalculationExpressConfigVO> commonPage = iCalculationExpressConfigService.getTaskPageList(params);
        return VO.response(ResponseEnum.SUCCESS, commonPage);
    }

    /**
     * 根据code查询
     *
     * @param id
     * @return
     */
    @GetMapping("/getExpressConfigById")
    @ApiOperation(value = "根据编号查询计算规则配置")
    public Object getExpressConfigByCode(Long id) {
        CalculationExpressConfig expressConfig = iCalculationExpressConfigService.getExpressConfigById(id);
        return VO.response(ResponseEnum.SUCCESS, expressConfig);
    }

    @Resource
    ExpressRunner runner;

    @Deprecated
    @RolesAllowed({"管理员", "组织单位", "考评办"})
    @PostMapping("planExpressExecute")
    @ApiOperation(value = "专项计算规则调用执行")
    public Object planExpressExecute(@RequestBody PlanExpressParams params) {
        Long ruleId = params.getRuleId();
        CalculationExpressConfig expressConfigByCode = iCalculationExpressConfigService.getExpressConfigById(ruleId);
        final String express = expressConfigByCode.getExpress();
        DefaultContext<String, Object> context = new DefaultContext<>();
        context.put(RuleParamsEnum.YEAR.getName(), params.getYear());
        context.put(RuleParamsEnum.PLAN_CODE.getName(), params.getEvaluationPlanCode());
        context.put(RuleParamsEnum.ASSESS_CYCLE.getName(), params.getAssessCycle());
        context.put(RuleParamsEnum.ASSESS_TIME.getName(), params.getAssessTime());
        context.put(RuleParamsEnum.APPROVE_STATUS.getName(), params.getApproveStatus());
        try {
            Object execute = runner.execute(express, context, null, false, false);
            return VO.response(ResponseEnum.SUCCESS, execute);
        } catch (Exception e) {
            e.printStackTrace();
            return VO.response(ResponseEnum.FAIL, e);
        }
    }
    @RolesAllowed({"管理员", "组织单位", "考评办"})
    @PostMapping("expressExecute")
    @ApiOperation(value = "调用执行计算规则")
    public Object expressExecute(@RequestBody @Valid ExpressParams expressParams) {
        Long ruleId = expressParams.getRuleId();
        CalculationExpressConfig expressConfig = iCalculationExpressConfigService.getExpressConfigById(ruleId);
        Integer ruleType = expressConfig.getType();
        DefaultContext<String, Object> context = new DefaultContext<>();
        expressParams.getParams().forEach((key, value) -> {
            String name = RuleParamsEnum.getName(ruleType, key);
            if (StringUtils.isBlank(name)) {
                LogUtils.warn("无效的参数:" + key);
//                throw new BizException(ResponseEnum.PARAM_ERROR);
            } else {
                context.put(name, value);
            }
        });
        final String express = expressConfig.getExpress();
        try {
            Object execute = runner.execute(express, context, null, false, false);
            return VO.response(ResponseEnum.SUCCESS, execute);
        } catch (Exception e) {
            LogUtils.error("计算表达式执行失败", e);
            return VO.response(ResponseEnum.FAIL, e);
        }
    }

    @PostMapping("expressTest")
    @ApiOperation(value = "计算规则测试")
    public Object expressTest(@RequestBody PlanExpressTestParams testParams) {
        DefaultContext<String, Object> context = new DefaultContext<>();
        List<Map<String, Object>> params = testParams.getParams();
        params.forEach(map -> {
            context.put(map.get("name").toString(), map.get("value"));
        });
        String express = testParams.getExpress();
        try {
            Object execute = runner.execute(express, context, null, false, false);
            return VO.response(ResponseEnum.SUCCESS, execute);
        } catch (Exception e) {
            e.printStackTrace();
            return VO.response(ResponseEnum.FAIL, e);
        }
    }

}
